#include "Frame.h"

#include <cstdio>

namespace stack {

void *Frame::getBaseAddress() {
	void *bp;
#if (defined __x86_64)
	asm("mov %%rbp, %0\n" : "=m"(bp));
#else
	asm("mov %%ebp, %0\n" : "=m"(bp));
#endif
	bp = *((void **) bp);
	if (bp == NULL) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return NULL;
	}
	return (void **) bp + 2;
}

void *Frame::getBaseAddress(size_t _frame) {
	void *bp;
#if (defined __x86_64)
	asm("mov %%rbp, %0\n" : "=m"(bp));
#else
	asm("mov %%ebp, %0\n" : "=m"(bp));
#endif
	for (size_t i = 0; i <= _frame; ++i) {
		bp = *((void **) bp);
		if (bp == NULL) {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return NULL;
		}
	}
	return (void **) bp + 2;
}

void *Frame::getReturnPc() {
	void *bp;
#if (defined __x86_64)
	asm("mov %%rbp, %0\n" : "=m"(bp));
#else
	asm("mov %%ebp, %0\n" : "=m"(bp));
#endif
	if (*((void **) bp) == NULL) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return NULL;
	}
	return *((void **) bp + 1);
}

void *Frame::getReturnPc(size_t _frame) {
	void *bp;
#if (defined __x86_64)
	asm("mov %%rbp, %0\n" : "=m"(bp));
#else
	asm("mov %%ebp, %0\n" : "=m"(bp));
#endif
	for (size_t i = 0; i < _frame; ++i) {
		bp = *((void **) bp);
		if (bp == NULL) {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return NULL;
		}
	}
	return *((void **) bp + 1);
}

Frame::Frame() {
}

Frame::~Frame() {
}

}
